package cn.easyplatform.studio.utils;

import cn.easyplatform.utils.SerializationUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.util.resource.Labels;

import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class ZipUtil {
    private static final Logger logger = LoggerFactory.getLogger(ZipUtil.class);

    private ZipUtil() {
        // 私用构造主法.因为此类是工具类.
    }


    public static void createZip(Object object, String zipName, String flnm) {
        byte[] data = SerializationUtils.serialize(object);
        ByteArrayOutputStream os = null;
        java.util.zip.ZipOutputStream zos = null;
        try {
            os = new ByteArrayOutputStream(data.length);
            zos = new java.util.zip.ZipOutputStream(os);
            zos.putNextEntry(new ZipEntry(zipName));
            //zos.putNextEntry(new ZipEntry(pid + ".dat"));
            zos.write(data);
            zos.finish();
            org.zkoss.zkmax.zul.Filedownload.save(os.toByteArray(), "application/zip", flnm);
            //org.zkoss.zkmax.zul.Filedownload.save(os.toByteArray(), "application/zip", vo.getId() + ".zip");
        } catch (IOException e) {
            WebUtils.showError(Labels.getLabel("editor.export.title"));
        } finally {
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(zos);
        }
    }

    public static Object unpackZip(byte[] data)
    {
        //byte[] data = ue.getMedia().getByteData();
        ByteArrayInputStream is = null;
        ZipInputStream zis = null;
        ByteArrayOutputStream bos = null;
        BufferedOutputStream dest = null;
        try {
            is = new ByteArrayInputStream(data);
            zis = new ZipInputStream(is);
            ZipEntry zip = zis.getNextEntry();
            if (zip != null) {
                data = new byte[2048];
                bos = new ByteArrayOutputStream();
                dest = new BufferedOutputStream(bos, 2048);
                int count;
                while ((count = zis.read(data, 0, 2048)) != -1)
                    dest.write(data, 0, count);
                dest.flush();
                Object object = (Object) SerializationUtils.deserialize(bos.toByteArray());
                return object;
            }
        } catch (IOException e) {
            WebUtils.showError(Labels.getLabel("editor.import.title"));
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(zis);
            IOUtils.closeQuietly(bos);
            IOUtils.closeQuietly(dest);
        }
        return null;
    }

    /**s
     * 压缩文件
     * @param srcFilePath 压缩源路径
     * @param destFilePath 压缩目的路径
     */
    public static void compress(String srcFilePath, String destFilePath) {
        //
        File src = new File(srcFilePath);

        if (!src.exists()) {
            throw new RuntimeException(srcFilePath + "不存在");
        }
        File zipFile = new File(destFilePath);

        try {

            FileOutputStream fos = new FileOutputStream(zipFile);
            ZipOutputStream zos = new ZipOutputStream(fos);
            String baseDir = "";
            compressbyType(src, zos, baseDir);
            zos.close();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        }
    }

    public static void unZip(File srcFile, String destDirPath) throws RuntimeException {
        long start = System.currentTimeMillis();
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
        }
        // 开始解压
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile);
            Enumeration<?> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                System.out.println("解压" + entry.getName());
                // 如果是文件夹，就创建个文件夹
                if (entry.isDirectory()) {
                    String dirPath = destDirPath + "/" + entry.getName();
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                    File targetFile = new File(destDirPath + "/" + entry.getName());
                    // 保证这个文件的父文件夹必须要存在
                    if(!targetFile.getParentFile().exists()){
                        targetFile.getParentFile().mkdirs();
                    }
                    targetFile.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    InputStream is = zipFile.getInputStream(entry);
                    FileOutputStream fos = new FileOutputStream(targetFile);
                    int len;
                    byte[] buf = new byte[1024];
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    // 关流顺序，先打开的后关闭
                    fos.close();
                    is.close();
                }
            }
            long end = System.currentTimeMillis();
            System.out.println("解压完成，耗时：" + (end - start) +" ms");
        } catch (Exception e) {
            throw new RuntimeException("unzip error from ZipUtils", e);
        } finally {
            if(zipFile != null){
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void unJarZip(File srcFile, String destDirPath) throws RuntimeException {
        long start = System.currentTimeMillis();
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
        }
        // 开始解压
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile);
            Enumeration<?> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                // 如果是文件夹，就创建个文件夹
                if (entry.isDirectory()) {
                    if (entry.getName().contains("maven") == false) {
                        String dirPath = destDirPath + "/" + entry.getName();
                        File dir = new File(dirPath);
                        dir.mkdirs();
                    }
                } else {
                    if (entry.getName().contains("maven") == false) {
                        // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                        File targetFile = new File(destDirPath + "/" + entry.getName());
                        // 保证这个文件的父文件夹必须要存在
                        if(!targetFile.getParentFile().exists()){
                            targetFile.getParentFile().mkdirs();
                        }
                        targetFile.createNewFile();
                        // 将压缩文件内容写入到这个文件中
                        InputStream is = zipFile.getInputStream(entry);
                        FileOutputStream fos = new FileOutputStream(targetFile);
                        int len;
                        byte[] buf = new byte[1024];
                        while ((len = is.read(buf)) != -1) {
                            fos.write(buf, 0, len);
                        }
                        // 关流顺序，先打开的后关闭
                        fos.close();
                        is.close();
                    }
                }
            }
            long end = System.currentTimeMillis();
        } catch (Exception e) {
            throw new RuntimeException("unzip error from ZipUtils", e);
        } finally {
            if(zipFile != null){
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

        /**
         * 按照原路径的类型就行压缩。文件路径直接把文件压缩，
         * @param src
         * @param zos
         * @param baseDir
         */
    private static void compressbyType(File src, ZipOutputStream zos,String baseDir) {

        if (!src.exists())
            return;
        System.out.println("压缩路径" + baseDir + src.getName());
        //判断文件是否是文件，如果是文件调用compressFile方法,如果是路径，则调用compressDir方法；
        if (src.isFile()) {
            //src是文件，调用此方法
            compressFile(src, zos, baseDir);

        } else if (src.isDirectory()) {
            //src是文件夹，调用此方法
            compressDir(src, zos, baseDir);

            }

        }

    /**
     * 压缩文件
     */
    private static void compressFile(File file, ZipOutputStream zos,String baseDir) {
        if (!file.exists())
            return;
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            ZipEntry entry = new ZipEntry(baseDir + file.getName());
            zos.putNextEntry(entry);
            int count;
            byte[] buf = new byte[1024];
            while ((count = bis.read(buf)) != -1) {
                zos.write(buf, 0, count);
            }
            bis.close();

        } catch (Exception e) {
            // TODO: handle exception

        }
    }

    /**
     * 压缩文件夹
     */
    private static void compressDir(File dir, ZipOutputStream zos, String baseDir) {
        if (!dir.exists())
            return;
        File[] files = dir.listFiles();
        if(files.length == 0){
            try {
                zos.putNextEntry(new ZipEntry(baseDir + dir.getName()+File.separator));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        for (File file : files) {
            compressbyType(file, zos, baseDir + dir.getName() + File.separator);
        }
    }
}
